// 实现 add(1)(2)...()
function add1(x) {
  let count = x
  return function add2(y) {
    if (!y) return count
    count += y
    return add2
  }
}
// console.log(add1(1)(2)())

function add1_(...args) {
  let a = (list) => {
    return list.reduce((x, y) =>  x + y)
  }
  let result = a(args)
  return function iner(...inner) {
    if (!inner.length) return result
    result += a(inner)
    return iner
  }
}

// console.log(add1_(2, 2)(2)(2)(4,2)())

function add(a){ 
  function name(b) {
    a += b
    return name
  }
  name.toString = function () {
    return a
  }
  return name
 }
//  console.log(add(1)(2).toString())

function sum(...a) {
  const s = (...b)=>sum(...[...a,...b]);//参数合并
  
  let result = a.reduce((x,y)=>{//当前阶段求值
    return x+y;
  })
  s.valueOf = function () {//函数出口
    return result;
  }
  return s;
}


// 实现 promise 失败重新请求 n次
let promisefn = () => {
  return new Promise((resolve,reject) => {
    setTimeout(() => {
      reject('失败')
    }, 100);
  })
}
function test(fn, times) {
  if (!times) return
  fn().then().catch(err => {
    console.log(err, times)
    times--
    test(fn, times)
  })
}
// test(promisefn, 10)

// 数组中两数之和等于等于目标值的下标
function find1(arr, target) {
  let map = new Map()
  let len = arr.length
  for(let i = 0; i< len; i++) {
    let n = target - arr[i]
    if (map.hasOwnProperty(n)) {
      return [map[n], i]
    }
    map[arr[i]] = i
  }
  return []
}

// console.log(find1([1,2,7], 8))

// for(var i = 0; i< 4; i++) {
//   (function name(i) {
//     setTimeout(() => {
//       console.log(i)
//     }, 10);
//   })(i)
// }




// "((*))*(((*))"
function check(str) {
  let left = [], s = []
  for (let i = 0; i< str.length; i++) {
    if (str[i] === '(') left.push(i)
    if (str[i] === '*') s.push(i)
    if (str[i] === ')') {
      if (left.length === 0) {
        if (s.length === 0) return false
        s.pop()
      } else {
        left.pop()
      }
    }
  }
  if (left.length > s.length) return false
  while(left.length && s.length) {
    if (left.pop() > s.pop()) return false
  }
  return true
}
// console.log(check('(**'))

// 平分根
function sqr (x) {
  if (x === 0 || x === 1) return 0
  let find = function (level, left, right, x) {
    if (right - left <= 1) return left
    mid = Math.floor((left + right)/2 )
    if (mid * mid > x) {
      right = mid
    } else {
      left = mid
    }
    return find(level + 1, left, right, x)
  }
  return find(0, 1, x, x)
}
// console.log(sqr(4))

// 防抖
function debounce(fn, delay) {
  let timer = null
  return function () {
    if (timer) {
      clearTimeout(timer) 
    }
    timer = setTimeout(fn,delay) 
  }
}
// 节流
function throttle(fn, delay) {
  let v = true
  return function () {
    if (!v) return
    v = false
    setTimeout(() => {
      fn()
      v = true
    }, delay);
  }
}
// 
let startTime = Date.now()
function throttle1(func, delay) {
  var curTime = Date.now();
  var remaining = delay - (curTime - this.startTime);
  var args = arguments;
  clearTimeout(this.timer);
  if (remaining <= 0) {
      func.apply(this, args);
      this.startTime = Date.now();
  } else {
      this.timer = setTimeout(func, remaining);
  }
}

// call

function call_(fn, obj, ...args) {
  if (obj ===null || obj === undefined) {
    obj = obj || window
  }
  obj.tmpFn = fn
  const result = obj.tmpFn(...args)
  delete obj.tmpFn
  return result
}
// apply

function apply_(fn, obj, args) {
  if (obj ===null || obj === undefined) {
    obj = obj || window
  }
  obj.tmpFn = fn
  const result = obj.tmpFn(...args)
  delete obj.tmpFn
  return result
}

// instanceof
function myInstanceOf(obj, type) {
  let protoObj = obj.__proto__
  while(protoObj) {
    if (protoObj === type.prototype) return true
    protoObj = protoObj.__proto__
  }
  return false
}
// function A () {}
// let a = new A()
// console.log(a instanceof A)
// console.log(myInstanceOf(a, A))

// new

function new_(fn, ...args) {
  const obj = {}
  const result = fn.apply(obj, args)
  if (result instanceof Object) return result
  obj.__proto__.constructor = fn
  return obj
}

// ajax

function ajax_(metho, url, callback, data, fla) {
  let xhr,
  flag = fla || true,
  method = metho.tuUpperCase()
  if (window.XMLHttpRequest) {
    xhr = new XMLHttpRequest
  } else {
    xhr = new ActiveXObject('Microsoft.XMLHTTP')
  }

  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4  && xhr.status === 200) {
      callback(xhr.responseText)
    }
  }

  if (method === 'GET') {
    var date = Date.now()
    xhr.open('GET', `${url}?${data}&timer=${date}`, flag)
    xhr.send()
  } else if (method === 'POST') {
    xhr.open('POST', url, flag)
    xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded')
    xhr.send(data)
  }
}



